import re
from typing import Tuple, Optional, Dict, Any


class DesignValueParser:
    """
    设计值技术指标解析器
    支持多种格式：范围值、公差值、单值、带符号值等，包括带单位的格式
    """
    
    # 预定义的正则表达式模式 - 使用re1, re2, re3...编号
    PATTERNS = {
        're1': re.compile(r'^([-]?[\d.]+)[~～]([-]?[\d.]+)$'),  # 范围值：35.6~36.0, 1.9～2.8 (支持中文波浪号)
        're2': re.compile(r'^([\d.]+)\(([^,]+),([^)]+)\)$'),   # 公差值：48.9(0,+0.4), 48(0,+0.2)
        're3': re.compile(r'^([\d.]+)±([\d.]+)$'),             # 对称公差：80810±800, 17842±120
        're7': re.compile(r'^([\d.]+)([a-zA-Z]+)±([\d.]+)([a-zA-Z]+)$'),  # 带单位的对称公差：11980mm±5mm
        're4': re.compile(r'^([≤≥＞＜=])([\d./]+)$'),           # 修改：允许数字、小数点和斜杠
        're5': re.compile(r'^([\d./]+)$'),                     # 修改：允许数字、小数点和斜杠
        're6': re.compile(r'^不小于\s*([\d./]+)$'),             # 修改：允许数字、小数点和斜杠
        're8': re.compile(r'^([≤≥＞＜=])([\d.]+)/([\d.]+)$'),  # 新增：专门处理分数格式
    }
    
    # 正则表达式描述映射
    PATTERN_DESCRIPTIONS = {
        're1': '范围值模式：数值~数值',
        're2': '公差值模式：数值(公差,公差)', 
        're3': '对称公差模式：数值±公差',
        're7': '带单位的对称公差模式：数值单位±公差单位',
        're4': '带符号单值模式：符号数值',
        're5': '简单单值模式：数值',
        're6': '文本描述模式：不小于数值',
        're8': '带符号分数模式：符号分子/分母'  # 新增描述
    }
    
    @classmethod
    def parse(cls, design_value: str) -> Dict[str, Any]:
        """
        解析设计值技术指标
        
        Returns:
            Dict containing:
            - type: 值类型 
            - original: 原始字符串
            - lower: 下限值
            - upper: 上限值
            - base: 基准值 (对于单值)
            - symbol: 符号 (对于带符号的值)
            - tolerance_lower: 下公差
            - tolerance_upper: 上公差
            - unit: 单位
            - matched_pattern: 匹配到的正则模式名称 (re1, re2等)
            - pattern_description: 正则模式描述
        """
        result = {
            'type': 'unknown',
            'original': design_value,
            'lower': None,
            'upper': None,
            'base': None,
            'symbol': None,
            'tolerance_lower': None,
            'tolerance_upper': None,
            'unit': None,  # 新增单位字段
            'matched_pattern': None,
            'pattern_description': None
        }
        
        # 去除空格
        value = design_value.strip()
        
        # 按优先级尝试匹配各种模式
        for pattern_name, pattern in cls.PATTERNS.items():
            match = pattern.match(value)
            if match:
                result['matched_pattern'] = pattern_name
                result['pattern_description'] = cls.PATTERN_DESCRIPTIONS.get(pattern_name, '未知模式')
                
                if pattern_name == 're1':
                    # 范围值：35.6~36.0
                    result['type'] = 'range'
                    lower, upper = float(match.group(1)), float(match.group(2))
                    result['lower'] = min(lower, upper)
                    result['upper'] = max(lower, upper)
                    result['base'] = (lower + upper) / 2
                    
                elif pattern_name == 're2':
                    # 公差值：48.9(0,+0.4)
                    result['type'] = 'tolerance'
                    base = float(match.group(1))
                    tol_lower_str = match.group(2).strip()
                    tol_upper_str = match.group(3).strip()
                    
                    result['base'] = base
                    result['tolerance_lower'] = cls._parse_tolerance_value(tol_lower_str, base)
                    result['tolerance_upper'] = cls._parse_tolerance_value(tol_upper_str, base)
                    
                    # 计算实际范围
                    lower = base + (result['tolerance_lower'] or 0)
                    upper = base + (result['tolerance_upper'] or 0)
                    result['lower'] = min(lower, upper)
                    result['upper'] = max(lower, upper)
                    
                elif pattern_name == 're3':
                    # 对称公差：80810±800
                    result['type'] = 'symmetric_tolerance'
                    base = float(match.group(1))
                    tolerance = float(match.group(2))
                    result['base'] = base
                    result['lower'] = base - tolerance
                    result['upper'] = base + tolerance
                    result['tolerance_lower'] = -tolerance
                    result['tolerance_upper'] = tolerance
                    
                elif pattern_name == 're7':
                    # 带单位的对称公差：11980mm±5mm
                    result['type'] = 'symmetric_tolerance_with_unit'
                    base = float(match.group(1))
                    unit = match.group(2)  # 获取单位
                    tolerance = float(match.group(3))
                    
                    result['base'] = base
                    result['unit'] = unit  # 保存单位
                    result['lower'] = base - tolerance
                    result['upper'] = base + tolerance
                    result['tolerance_lower'] = -tolerance
                    result['tolerance_upper'] = tolerance
                    
                elif pattern_name == 're4':
                    # 带符号单值：≤1.5 或 ≤1/4
                    result['type'] = 'single_with_symbol'
                    symbol = match.group(1)
                    value_str = match.group(2)
                    
                    # 处理分数格式
                    if '/' in value_str:
                        numerator, denominator = value_str.split('/')
                        try:
                            value_num = float(numerator) / float(denominator)
                        except ValueError:
                            value_num = None
                    else:
                        try:
                            value_num = float(value_str)
                        except ValueError:
                            value_num = None
                    
                    if value_num is None:
                        return result  # 解析失败，返回未知类型
                        
                    result['symbol'] = symbol
                    result['base'] = value_num
                    
                    # 根据符号确定范围
                    if symbol == '≤':
                        result['lower'] = None
                        result['upper'] = value_num
                    elif symbol == '≥':
                        result['lower'] = value_num
                        result['upper'] = None
                    elif symbol in ['＞', '>']:
                        result['lower'] = value_num
                        result['upper'] = None
                    elif symbol in ['＜', '<']:
                        result['lower'] = None
                        result['upper'] = value_num
                    elif symbol == '=':
                        result['lower'] = value_num
                        result['upper'] = value_num
                        
                elif pattern_name == 're5':
                    # 简单单值：0.8 或 1/4
                    result['type'] = 'simple_single'
                    value_str = match.group(1)
                    
                    # 处理分数格式
                    if '/' in value_str:
                        numerator, denominator = value_str.split('/')
                        try:
                            value_num = float(numerator) / float(denominator)
                        except ValueError:
                            value_num = None
                    else:
                        try:
                            value_num = float(value_str)
                        except ValueError:
                            value_num = None
                    
                    if value_num is None:
                        return result
                        
                    result['base'] = value_num
                    result['lower'] = value_num
                    result['upper'] = value_num
                    
                elif pattern_name == 're6':
                    # 文本描述值：不小于51
                    result['type'] = 'text_description'
                    value_str = match.group(1)
                    
                    # 处理分数格式
                    if '/' in value_str:
                        numerator, denominator = value_str.split('/')
                        try:
                            value_num = float(numerator) / float(denominator)
                        except ValueError:
                            value_num = None
                    else:
                        try:
                            value_num = float(value_str)
                        except ValueError:
                            value_num = None
                    
                    if value_num is None:
                        return result
                        
                    result['base'] = value_num
                    result['lower'] = value_num
                    result['upper'] = None
                    result['symbol'] = '≥'
                
                elif pattern_name == 're8':
                    # 专门处理带符号的分数：≤1/4
                    result['type'] = 'single_with_symbol'
                    symbol = match.group(1)
                    numerator = float(match.group(2))
                    denominator = float(match.group(3))
                    
                    value_num = numerator / denominator
                    result['symbol'] = symbol
                    result['base'] = value_num
                    
                    # 根据符号确定范围
                    if symbol == '≤':
                        result['lower'] = None
                        result['upper'] = value_num
                    elif symbol == '≥':
                        result['lower'] = value_num
                        result['upper'] = None
                    elif symbol in ['＞', '>']:
                        result['lower'] = value_num
                        result['upper'] = None
                    elif symbol in ['＜', '<']:
                        result['lower'] = None
                        result['upper'] = value_num
                    elif symbol == '=':
                        result['lower'] = value_num
                        result['upper'] = value_num
                
                break  # 匹配成功即退出
        
        return result
    
    @classmethod
    def _parse_tolerance_value(cls, tol_str: str, base_value: float) -> Optional[float]:
        """解析公差值"""
        tol_str = tol_str.strip()
        
        if tol_str == '0':
            return 0.0
            
        # 处理 +0.4, -0.2 这样的格式
        if tol_str.startswith('+') or tol_str.startswith('-'):
            return float(tol_str)
            
        # 处理 0 这样的格式
        try:
            return float(tol_str)
        except ValueError:
            return None
    
    @classmethod
    def get_numeric_range(cls, design_value: str) -> Tuple[Optional[float], Optional[float]]:
        """
        获取设计值的数值范围
        
        Returns:
            Tuple[lower, upper]
        """
        parsed = cls.parse(design_value)
        return parsed['lower'], parsed['upper']
    
    @classmethod
    def get_base_value(cls, design_value: str) -> Optional[float]:
        """获取基准值"""
        parsed = cls.parse(design_value)
        return parsed['base']




def test_parser():
    """测试设计值解析器"""
    test_cases = [
        "48.9(0,+0.4)",    # 公差值 - re2
        "1.9～2.8",        # 范围值 (中文波浪号) - re1
        "48(0,+0.2)",      # 公差值 - re2
        "80810±800",       # 对称公差 - re3
        "17842±120",       # 对称公差 - re3
        "≤1.5",           # 带符号单值 - re4
        "≤1/4",           # 带符号分数 - re4 或 re8
        "不小于51",        # 文本描述值 - re6
        "不小于50.5",      # 文本描述值 - re6
        "48.3(0,+0.2)",   # 公差值 - re2
        "35.6~36.0",      # 范围值 - re1
        "0.8",            # 简单单值 - re5
        "1/4",            # 简单分数 - re5
        "≥5.0",           # 带符号单值 - re4
        "11980mm±5mm",    # 带单位对称公差 - re7
    ]

    
    print("设计值解析器测试结果:")
    print("=" * 80)
    
    for test_case in test_cases:
        result = DesignValueParser.parse(test_case)

        # 先单独保存每个要输出的变量
        raw_val = test_case
        type_val = result['type']
        matched_pattern_val = result.get('matched_pattern', '')
        pattern_desc_val = result.get('pattern_description', '')
        lower_val = result['lower']
        upper_val = result['upper']
        base_val = result['base']
        symbol_val = result['symbol']
        tol_lower_val = result['tolerance_lower']
        tol_upper_val = result['tolerance_upper']

        # 打印
        print(f"原始值: {raw_val:15} | 类型: {type_val:20} | 正则: {matched_pattern_val:5}")
        print(f"        描述: {pattern_desc_val}")
        print(f"        范围: [{lower_val} ~ {upper_val}] | 基准: {base_val} | 符号: {symbol_val}")
        if tol_lower_val is not None or tol_upper_val is not None:
            print(f"        公差: [{tol_lower_val}, {tol_upper_val}]")
        print("-" * 80)


if __name__ == "__main__":
    test_parser()